//
//  ATViewController.m
//  AsyncTaskTrigger
//
//  Created by zuosong on 09/17/2020.
//  Copyright (c) 2020 zuosong. All rights reserved.
//

#import "ATViewController.h"
#import "AsyncTaskManager.h"
#import "AsyncTaskItem.h"
#import "AsyncTaskTrigger.h"
#import "HAMLogOutputWindow.h"

static NSInteger loopCount = 5;

@interface ATViewController ()

@property (strong, nonatomic) IBOutlet UISwitch *switchView;
@property (strong, nonatomic) IBOutlet UILabel *statusLabel;
@property (strong, nonatomic) IBOutlet UIButton *serailBtn;
@property (strong, nonatomic) IBOutlet UIButton *concurrentBtn;
@property (strong, nonatomic) IBOutlet UIButton *triggerSerialBtn;
@property (strong, nonatomic) IBOutlet UIButton *triggerConcurrentBtn;

@property (nonatomic, strong) NSOperationQueue *taskOperationQueue;

@end

@implementation ATViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.

    
    
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //    [self testFuntion_taskOperationQueue];
    //    [self testFunction_BlockOperation];
    //    [self testFunction_DISPATCH];
    //    [self testFunction_DISPATCH_Group];
    
}
#pragma mark - *****  Actioin  *****

- (void)firstQueueActionWithSemaphore:(dispatch_semaphore_t)smp {
    NSLog(@"kael queue --->A1 ----------");
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->A2");
        }
        NSLog(@"kael queue --->A3 ----------");
        dispatch_semaphore_signal(smp);
    });
}

- (void)secondQueueActionWithSemaphore:(dispatch_semaphore_t)smp {
    NSLog(@"kael queue --->B1 ----------");
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->B2");
        }
        NSLog(@"kael queue --->B3 ----------");
        dispatch_semaphore_signal(smp);
    });
}

- (void)thirdQueueActionWithSemaphore:(dispatch_semaphore_t)smp smpCount:(NSInteger)smpCount {
    NSLog(@"kael test -- 0");

    for (int i=0; i<smpCount; i++) {
        NSLog(@"kael wait start %d",i);
        dispatch_semaphore_wait(smp, DISPATCH_TIME_FOREVER);
        NSLog(@"kael test -- 0-1");
        NSLog(@"kael wait end %d",i);
    }
    NSLog(@"kael test -- finished ----------------");
}

#pragma mark - *****  Funtion  *****

- (void)testFuntion_taskOperationQueue {
    _taskOperationQueue = [[NSOperationQueue alloc] init];;
    _taskOperationQueue.maxConcurrentOperationCount = 10;
    [_taskOperationQueue addObserver:self forKeyPath:@"operations" options:0 context:nil];
    
    dispatch_semaphore_t mySemaphore = dispatch_semaphore_create(0);
    
    NSInteger semaphoreNum = 2;
    
    [_taskOperationQueue addOperationWithBlock:^{
        [self firstQueueActionWithSemaphore:mySemaphore];
    }];

    [_taskOperationQueue addOperationWithBlock:^{
        [self secondQueueActionWithSemaphore:mySemaphore];
    }];

    [_taskOperationQueue addOperationWithBlock:^{
        [self thirdQueueActionWithSemaphore:mySemaphore smpCount:semaphoreNum];
    }];
}

- (void)testFunction_BlockOperation {
    dispatch_semaphore_t mySemaphore = dispatch_semaphore_create(0);
    
    NSInteger semaphoreNum = 2;
    
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        [self firstQueueActionWithSemaphore:mySemaphore];
    }];

    [blockOperation addExecutionBlock:^{
        [self secondQueueActionWithSemaphore:mySemaphore];
    }];

    [blockOperation addExecutionBlock:^{
        [self thirdQueueActionWithSemaphore:mySemaphore smpCount:semaphoreNum];
    }];

    [blockOperation start];
}

- (void)testFunction_DISPATCH{
    
    dispatch_queue_t kqueue = dispatch_queue_create("kael_queue", DISPATCH_QUEUE_SERIAL);
    dispatch_semaphore_t mySemaphore = dispatch_semaphore_create(0);
    
    NSInteger semaphoreNum = 2;

    dispatch_async(kqueue, ^{
        [self firstQueueActionWithSemaphore:mySemaphore];
    });
    
    dispatch_async(kqueue, ^{
        [self secondQueueActionWithSemaphore:mySemaphore];
    });
    
    dispatch_async(kqueue, ^{
        [self thirdQueueActionWithSemaphore:mySemaphore smpCount:semaphoreNum];
    });
}

- (void)testFunction_DISPATCH_Group {
    dispatch_queue_t kqueue = dispatch_queue_create("kael_queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t kgroup = dispatch_group_create();

    dispatch_group_enter(kgroup);

    dispatch_group_async(kgroup, kqueue, ^{
        NSLog(@"kael queue --->A1 ----------");
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            // 处理耗时操作的代码块...
            for (int i=0; i<loopCount; i++) {
                NSLog(@"kael queue --->A2");
            }
            NSLog(@"kael queue --->A3 ----------");
            dispatch_group_leave(kgroup);
        });
    });
    
    dispatch_group_enter(kgroup);

    dispatch_group_async(kgroup, kqueue, ^{
        NSLog(@"kael queue --->B1 ----------");
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            // 处理耗时操作的代码块...
            for (int i=0; i<loopCount; i++) {
                NSLog(@"kael queue --->B2");
            }
            NSLog(@"kael queue --->B3 ----------");
            dispatch_group_leave(kgroup);
        });
    });
    
    dispatch_group_notify(kgroup, kqueue, ^{
        NSLog(@"kael test -- 0");
        NSLog(@"kael test -- finished ----------------");
    });
    
}

- (void)faultsGroup {
    dispatch_queue_t kqueue = dispatch_queue_create("kael_queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t kgroup = dispatch_group_create();

    dispatch_group_enter(kgroup);

    dispatch_group_async(kgroup, kqueue, ^{
        NSLog(@"kael queue --->A1 ----------");
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            // 处理耗时操作的代码块...
            for (int i=0; i<loopCount; i++) {
                NSLog(@"kael queue --->A2");
            }
            NSLog(@"kael queue --->A3 ----------");
        });
        dispatch_group_leave(kgroup);
    });
    

    dispatch_group_enter(kgroup);

    dispatch_group_async(kgroup, kqueue, ^{
        NSLog(@"kael queue --->B1 ----------");
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            // 处理耗时操作的代码块...
            for (int i=0; i<loopCount; i++) {
                NSLog(@"kael queue --->B2");
            }
            NSLog(@"kael queue --->B3 ----------");
        });
        dispatch_group_leave(kgroup);
    });
    
    dispatch_group_notify(kgroup, kqueue, ^{
        NSLog(@"kael test -- 0");
        NSLog(@"kael test -- finished ----------------");
    });
}

#pragma mark - *****  KVO 回调  *****

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if (object == _taskOperationQueue && [keyPath isEqualToString:@"operations"])
    {
        if (_taskOperationQueue && _taskOperationQueue.operations.count == 0){
            //other operation
            [_taskOperationQueue setSuspended:YES];
            NSLog(@"ksel operationQueue finished KVO");
        }
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark 测试

- (void)actionBlockA{
    NSLog(@"kael queue --->A1 ----------");
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->A2");

        }
        NSLog(@"kael queue --->A3 ----------");
        
        [[AsyncTaskManager shareManager] sendSemaphore];
    });
}

- (void)actionBlockAWithComplet:(void (^)(void))completBlock{
    NSLog(@"kael queue --->C1 ----------");

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->C2");
        }
        NSLog(@"kael queue --->C3 ----------");
        completBlock();
    });
}

- (void)actionBlockB{
    NSLog(@"kael queue --->B1 ----------");

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->B2");

        }
        NSLog(@"kael queue --->B3 ----------");

        [[AsyncTaskManager shareManager] sendSemaphore];
    });
}

- (void)actionBlockBWithComplet:(void (^)(void))completBlock{
    NSLog(@"kael queue --->D1 ----------");

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->D2");

        }
        NSLog(@"kael queue --->D3 ----------");

        completBlock();
    });
}

- (void)actionBlockEEWithComplet:(void (^)(void))completBlock{
    NSLog(@"kael queue --->E1 ----------");

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->E2");
        }
        NSLog(@"kael queue --->E3 ----------");
        completBlock();
    });
}

- (void)actionBlockFFWithComplet:(void (^)(void))completBlock{
    NSLog(@"kael queue --->F1 ----------");

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        for (int i=0; i<loopCount; i++) {
            NSLog(@"kael queue --->F2");

        }
        NSLog(@"kael queue --->F3 ----------");

        completBlock();
    });
}


- (IBAction)switchViewAction:(id)sender {
    
    NSLog(@"switch %@",self.switchView.isOn ? @"开" : @"关");
    self.statusLabel.text = self.switchView.isOn ? @"开启Handler" : @"关闭Handler";
    
}


- (IBAction)serailBtnAction:(id)sender {
    if (self.switchView.isOn) {
        [[AsyncTaskManager shareManager] addSerialHandlerActionBlock:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockAWithComplet:^{
                semaphoreHandle();
            }];
        }];
        
        [[AsyncTaskManager shareManager] addSerialHandlerActionBlock:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockBWithComplet:^{
                semaphoreHandle();
            }];
        }];
        
        [[AsyncTaskManager shareManager] startSerialActionWithCompletBlock:^{
            NSLog(@"kael -- 所有的任务都完成了");
        }];
        
    }else{
        [[AsyncTaskManager shareManager] addSerialActionBlock:^{
            [self actionBlockA];
        } ];
        [[AsyncTaskManager shareManager] addSerialActionBlock:^{
            [self actionBlockB];
        }];
        
        [[AsyncTaskManager shareManager] startSerialActionWithCompletBlock:^{
            NSLog(@"kael -- 所有的任务都完成了");
        }];
    }
    
}

- (IBAction)concurrentBtnAction:(id)sender {
    if (self.switchView.isOn) {
        
        [[AsyncTaskManager shareManager] addConcurrentHandlerActionBlock:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockA];
        }];
        
        [[AsyncTaskManager shareManager] addConcurrentHandlerActionBlock:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockB];
        }];
        
        [[AsyncTaskManager shareManager] startConcurrentActionWithCompletBlock:^{
            NSLog(@"kael -- 所有的任务都完成了1");
        }];
        
    }else{
        [[AsyncTaskManager shareManager] addConcurrentActionBlock:^{
            [self actionBlockA];
        }];
        
        [[AsyncTaskManager shareManager] addConcurrentActionBlock:^{
            [self actionBlockB];
        }];
        
        [[AsyncTaskManager shareManager] addConcurrentActionBlock:^{
            [self actionBlockA];
        }];
        
        [[AsyncTaskManager shareManager] addConcurrentActionBlock:^{
            [self actionBlockB];
        }];
        
        [[AsyncTaskManager shareManager] startConcurrentActionWithCompletBlock:^{
            NSLog(@"kael -- 所有的任务都完成了1");
        }];
    }
}

- (IBAction)triggerSerialBtnAction:(id)sender {
    // 两个串行任务
//    [self serailBtnAction:sender];
//    return;
    AsyncTaskTrigger *trigger = [AsyncTaskTrigger shareTrigger];
    
    __weak typeof (&*trigger)wtrigger = trigger;
    
    NSString *groupKey = @"serial_group_serial";

    if (self.switchView.isOn) {
        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockAWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];

        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockBWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];
        
        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockAWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];
        
        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockBWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];
        
        [trigger startTaskActionWithGroupKey:groupKey completBlock:^{
            NSLog(@"kael -- 所有的任务都完成了");
        }];
        
    } else{
        [trigger addTaskAction:^{
            [self actionBlockAWithComplet:^{
                [[AsyncTaskTrigger shareTrigger] sendSemaphoreToGroupKey:groupKey];
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];

        [trigger addTaskAction:^{
            [self actionBlockBWithComplet:^{
                [wtrigger sendSemaphoreToGroupKey:groupKey];
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];
        
        [trigger addTaskAction:^{
            [self actionBlockAWithComplet:^{
                [wtrigger sendSemaphoreToGroupKey:groupKey];
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];
        
        [trigger addTaskAction:^{
            [self actionBlockBWithComplet:^{
                [wtrigger sendSemaphoreToGroupKey:groupKey];
            }];
        } asyncType:LXTaskAsyncTypeSerial groupKey:groupKey completBlock:nil];
        
        [trigger startTaskActionWithGroupKey:groupKey completBlock:^{
            NSLog(@"kael -- 所有的任务都完成了");
        }];
    }
}

- (IBAction)triggerConcurrentBtnAction:(id)sender {
    
    // 两个并发任务
    AsyncTaskTrigger *trigger = [AsyncTaskTrigger shareTrigger];
    __weak typeof (&*trigger)wtrigger = trigger;

    if (self.switchView.isOn) {
        NSString *groupKey = @"serial_group_Concurrent_on";
        [trigger prepareTaskGroupWithAsyncType:LXTaskAsyncTypeConcurrent groupKey:groupKey];
        
        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockAWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeConcurrent groupKey:groupKey completBlock:nil];
        
        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockBWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeConcurrent groupKey:groupKey completBlock:nil];
        
        [trigger addTaskHandlerAction:^(LXTaskActionBlock  _Nullable semaphoreHandle) {
            [self actionBlockBWithComplet:^{
                semaphoreHandle();
            }];
        } asyncType:LXTaskAsyncTypeConcurrent groupKey:groupKey completBlock:nil];

        [trigger startTaskActionWithGroupKey:groupKey completBlock:^{
            NSLog(@"kael -- 所有的任务都完成了2");
        }];
        
        
        self.switchView.on = NO;
        [self triggerConcurrentBtnAction:self.switchView];
    } else{
        NSString *groupKey = @"serial_group_Concurrent_off";
        [trigger prepareTaskGroupWithAsyncType:LXTaskAsyncTypeConcurrent groupKey:groupKey];

        [trigger addTaskAction:^{
            [self actionBlockEEWithComplet:^{
                [wtrigger sendSemaphoreToGroupKey:groupKey];
            }];
        } groupKey:groupKey];
        
        [trigger addTaskAction:^{
            [self actionBlockFFWithComplet:^{
                [wtrigger sendSemaphoreToGroupKey:groupKey];
            }];
        } groupKey:groupKey];
        
        [trigger startTaskActionWithGroupKey:groupKey completBlock:^{
            NSLog(@"kael -- 所有的任务都完成了3");
        }];
        
//        self.switchView.on = YES;
//        [self triggerConcurrentBtnAction:self.switchView];
    }
    
    
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
